(define nil ())

(define (fold-left op initial sequence)
  (define (iter result rest)
    (if (null? rest)
        result
        (iter (op result (car rest))
              (cdr rest))))
  (iter initial sequence))

(define (accumulate op initial sequence)
  (if (null? sequence)
      initial
      (op (car sequence)
          (accumulate op initial (cdr sequence)))))
(define fold-right accumulate)

(define (reverse-fold-right sequence)
  (fold-right (lambda (x y) (append y (list x)))
              nil sequence))

(define (reverse-fold-left sequence)
  (fold-left (lambda (x y) (cons y x)) nil sequence))

(define (enumerate-interval i j)
  (if (> i j) nil (cons i (enumerate-interval (+ i 1) j))))
(define (enumerate-interval-k i j k)
  (if (> i j) nil (cons i (enumerate-interval-k (+ i k) j k))))

(define (flatmap proc sequence)
  (accumulate append nil (map proc sequence)))

(define (remove item sequence)
  (filter (lambda (x) (not (= x item))) sequence))
(define (permutations s)
  (if (null? s)
      (list nil)
      (flatmap (lambda (x)
                 (map (lambda (p) (cons x p))
                      (permutations (remove x s))))
               s)))
(define (unique-pairs n)
  (flatmap
   (lambda (i)
     (accumulate cons nil
                 (map (lambda (j) (cons j i))
                      (enumerate-interval 1 (- i 1)))))
   (enumerate-interval 1 n)))

(define (and-all items)
  (cond ((null? items) #t)
        ((car items) (and-all (cdr items)))
        (else #f)))

(define (prime? x)
  (if (= 2 x) #t
      (and-all (map (lambda (p) (< 0 (remainder x p)))
                (cons 2 (enumerate-interval-k 3 (/ x 2) 2))))))
